package dk.dtu.android.rejseplanen;

import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import dk.dtu.android.transport.RestClient;

import android.util.Log;

public class Rejseplanen {

	private final static String baseURL = "http://xmlopen.rejseplanen.dk/bin/rest.exe/";

	private static NodeList xmlParser(String xmlURI) {
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		NodeList nodes = null;
		try {
			DocumentBuilder db = dbFactory.newDocumentBuilder();
			Document doc = db.parse(xmlURI);

			Element rootEl = doc.getDocumentElement();
			nodes = rootEl.getChildNodes();
		} catch (ParserConfigurationException e) {
			Log.e("RejseplanenTest", "ParserConfigurationException: " + e);
		} catch (SAXException e) {
			Log.e("RejseplanenTest", "SAXException: " + e);
		} catch (IOException e) {
			Log.e("RejseplanenTest", "IOException: " + e);
		}

		return nodes;
	}

	private static String changeBoolToString(Boolean value) {
		if (value)
			return "1";
		else
			return "0";
	}

	public static ArrayList<StopLocation> location(String input) {
		String URL = baseURL + "location";
		
		ArrayList<StopLocation> tmpLoc = new ArrayList<StopLocation>();

		List<NameValuePair> params = new LinkedList<NameValuePair>();
		params.add(new BasicNameValuePair("input", input));

		NodeList nodes = xmlParser(RestClient.EncodeURL(URL, params));
		Log.d("Rejseplanen", "URL: " + RestClient.EncodeURL(URL, params));

		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);

			if (node instanceof Element) {
				Log.d("RejseplanenTest", "node Name" + node.getNodeName());
				Element child = (Element) node;
				StopLocation loc = new StopLocation();
				loc.id = child.getAttribute("id");
				loc.name = child.getAttribute("name");
				loc.x = child.getAttribute("x");
				loc.y = child.getAttribute("y");
				loc.dist = null;
				tmpLoc.add(loc);
			}
		}
		return tmpLoc;
	}

	public static ArrayList<StopLocation> stopsNearby(List<NameValuePair> params) {
		String URL = baseURL + "stopsNearby";
		
		ArrayList<StopLocation> tmpStops = new ArrayList<StopLocation>();

		Log.d("Rejseplanen", "URL: " + RestClient.EncodeURL(URL, params));
		NodeList stopsNodes = xmlParser(RestClient.EncodeURL(URL, params));

		for (int i = 0; i < stopsNodes.getLength(); i++) {
			Node stopsNode = stopsNodes.item(i);

			if (stopsNode instanceof Element) {
				Log.d("RejseplanenTest", "node Name" + stopsNode.getNodeName());
				Element child = (Element) stopsNode;
				StopLocation loc = new StopLocation();
				loc.id = child.getAttribute("id");
				loc.name = child.getAttribute("name");
				loc.x = child.getAttribute("x");
				loc.y = child.getAttribute("y");
				loc.dist = child.getAttribute("dist");
				tmpStops.add(loc);
			}
		}

		return tmpStops;
	}

	public static ArrayList<ArrayList<Leg>> trip(List<NameValuePair> params) {
		String URL = baseURL + "trip";
		
		ArrayList<Leg> tmpLeg = new ArrayList<Leg>();
		ArrayList<ArrayList<Leg>> tmpTrip = new ArrayList<ArrayList<Leg>>();
		
		Log.d("Rejseplanen", "URL: " + RestClient.EncodeURL(URL, params));
		NodeList tripNodes = xmlParser(RestClient.EncodeURL(URL, params));

		for (int i = 0; i < tripNodes.getLength(); i++) {
			Node tripNode = tripNodes.item(i);
			Log.d("RejseplanenTest", "tripNode Name: " + tripNode.getNodeName());

			NodeList legNodes = tripNode.getChildNodes();
			for (int j = 0; j < legNodes.getLength(); j++) {
				Node legNode = legNodes.item(j);

				if (legNode instanceof Element) {
					Log.d("RejseplanenTest",
							"legNode Name: " + legNode.getNodeName());
					Element legChild = (Element) legNode;
					Leg leg = new Leg();
					leg.legName = legChild.getAttribute("name");
					leg.legType = legChild.getAttribute("type");

					NodeList attrNodes = legNode.getChildNodes();
					for (int k = 0; k < attrNodes.getLength(); k++) {
						Node attrNode = attrNodes.item(k);
						if (attrNode.hasAttributes()) {
							if (attrNode instanceof Element) {
								Log.d("RejseplanenTest", "attrNode Name: "
										+ attrNode.getNodeName());
								Element attrChild = (Element) attrNode;
								if (attrNode.getNodeName().equals("Origin")) {
									Log.d("RejseplanenTest", "Origin!");
									leg.Orig = new OrigDest();
									leg.Orig.OrigDestName = attrChild
											.getAttribute("name");
									leg.Orig.OrigDestType = attrChild
											.getAttribute("type");
									leg.Orig.OrigDestTime = attrChild
											.getAttribute("time");
									leg.Orig.OrigDestDate = attrChild
											.getAttribute("date");
								}
								if (attrNode.getNodeName()
										.equals("Destination")) {
									Log.d("RejseplanenTest", "Destination!");
									leg.Dest = new OrigDest();
									leg.Dest.OrigDestName = attrChild
											.getAttribute("name");
									leg.Dest.OrigDestType = attrChild
											.getAttribute("type");
									leg.Dest.OrigDestTime = attrChild
											.getAttribute("time");
									leg.Dest.OrigDestDate = attrChild
											.getAttribute("date");
								}
								tmpLeg.add(leg);
							}
						}
					}
				}
			}
			tmpTrip.add(tmpLeg);
		}

		return tmpTrip;
	}

	public static ArrayList<DepartureBoard> departureBoard(String stationId,
			String date, String time) {
		return departureBoard(stationId, date, time, true, true, true);
	}

	public static ArrayList<DepartureBoard> departureBoard(String stationId,
			String date, String time, Boolean useTog, Boolean useBus,
			Boolean useMetro) {
		String URL = baseURL + "departureBoard";
		
		ArrayList<DepartureBoard> tmpDepBoard = new ArrayList<DepartureBoard>();

		List<NameValuePair> params = new LinkedList<NameValuePair>();
		params.add(new BasicNameValuePair("id", stationId));
		if (date != null && time != null) {
			params.add(new BasicNameValuePair("date", date));
			params.add(new BasicNameValuePair("time", time));
		}
		if (useTog != null)
			params.add(new BasicNameValuePair("useTog",
					changeBoolToString(useTog)));
		if (useBus != null)
			params.add(new BasicNameValuePair("useBus",
					changeBoolToString(useBus)));
		if (useMetro != null)
			params.add(new BasicNameValuePair("useMetro",
					changeBoolToString(useMetro)));
		
		Log.d("Rejseplanen", "URL: " + RestClient.EncodeURL(URL, params));
		NodeList nodes = xmlParser(RestClient.EncodeURL(URL, params));

		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);

			if (node instanceof Element) {
				Log.d("RejseplanenTest", "node: " + node.getNodeName());
				Element child = (Element) node;
				DepartureBoard db = new DepartureBoard();
				db.name = child.getAttribute("name");
				db.type = child.getAttribute("type");
				db.stop = child.getAttribute("stop");
				db.time = child.getAttribute("time");
				db.date = child.getAttribute("date");
				db.direction = child.getAttribute("direction");
				tmpDepBoard.add(db);
			}
		}

		return tmpDepBoard;
	}
	
	public static int northSouth(String direction) {
		
		int returnVal = -1; 
		
		ArrayList<String> northBound = new ArrayList<String>();
		ArrayList<String> southBound = new ArrayList<String>();
		
		northBound.add("Farum st");
		northBound.add("Holte st");
		northBound.add("Hillerød st");
		northBound.add("Klampenborg st");
		northBound.add("Hellerup st");
		northBound.add("Østerport st");
		northBound.add("Vanløse (Metro)");
		northBound.add("Vanløse (Metro)");

		southBound.add("Køge st");
		southBound.add("Høje Taastrup st");
		southBound.add("Hundige st");
		southBound.add("Frederikssund st");
		southBound.add("Ballerup st");
		southBound.add("Solrød Strand St");
		southBound.add("Lufthavnen (Metro)");
		southBound.add("Vestamager");
		
		for (int i = 0; i < northBound.size(); i++) {
			Log.d("Rejseplanen", "Direction: " + direction);
			if (northBound.get(i).equals(direction)) {
				returnVal = 1;
				break;
			}
			else if(southBound.get(i).equals(direction)) {
				returnVal = 0;
				break;
			}
		}
		
		return returnVal;
	}
}
